﻿#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

using namespace std;


//int main()
//{
//	const int a = 10;//只读不可写
//	/*int& ra = a;*/ //不能放大为可读可写，权限放大，与a是同一块空间
//	//int raa = a;//这里是单纯拷贝，与a是不同的空间，不存在权限放大
//	const int& ra = a;
//
//	//权限可以被缩小，但不能被放大
//	int b = 20;
//	const int& rb = b;//只是别名rb的权限是只读不可写，b的权限依旧是可读可写
//	b++;
//	/*rb++;*/
//
//	const int& rc = 30;//常量
//	const int& rd = (a + b);//a+b的结果会存储在临时变量中，临时变量有常量属性
//
//	double c = 12.34;
//	int i = c;
//	const int& re = c;//double类型转换成int,中间产生临时变量，有常量属性
//	double& rf = c;
//
//	//空引用
//	/*int* ptr = NULL;
//	int& ri = *ptr;
//	++ri;*/
//
//	
//	return 0;
//}

//指针和引⽤的关系
//语法概念上引⽤是⼀个变量的取别名不开空间，指针是存储⼀个变量地址，要开空间。
//引⽤在定义时必须初始化，指针建议初始化，但是语法上不是必须的。
//引⽤在初始化时引⽤⼀个对象后，就不能再引⽤其他对象；⽽指针可以在不断地改变指向对象。
//引⽤可以直接访问指向对象，指针需要解引⽤才是访问指向对象。
//sizeof中含义不同，引⽤结果为引⽤类型的⼤⼩，但指针始终是地址空间所占字节个数(32位平台下
//	占4个字节，64位下是8byte)
//指针很容易出现空指针和野指针的问题，引⽤很少出现，引⽤使⽤起来相对更安全⼀些。

#include "F.h"

//int main()
//{
//	// 链接错误：⽆法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z)
//	//inline不建议声明和定义分离到两个⽂件，分离会导致链接错误。因为inline被展开，就没有函数地
//	//址，链接时会出现报错。
//	Func(10);
//	//正确做法：将内联函数的定义和声明都放在头文件中
//
//	return 0;
//}

//class Date
//{
//public:
//	void DateInit(int year, int month, int day)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//
//	void DatePrint()
//	{
//		cout << _year << " " << _month << " " << _day << endl;
//	}
//
//private:
//	// 为了区分成员变量，⼀般习惯上成员变量
//   // 会加⼀个特殊标识，如_ 或者 m开头
//	int _year;//year_或者m_year
//	int _month;
//	int _day;
//
//};
//
//int main()
//{
//	Date st;
//
//	st.DateInit(2004, 8, 27);
//	st.DatePrint();
//
//	return 0;
//}


// C++升级struct升级成了类
// 1、类⾥⾯可以定义函数
// 2、struct名称就可以代表类型 

// C++兼容C中struct的⽤法
//typedef struct ListNodeC
//{
//	int val;
//	struct ListNoddeC* next;
//}ListNodeC;
//
// 不再需要typedef，ListNodeCPP就可以代表类型
//struct ListNodeCpp
//{
//	void ListInit(int x)
//	{
//		next = nullptr;
//		val = x;
//	}
//
//	ListNodeCpp* next;
//	int val;
//};
//
//int main()
//{
//	return 0;
//}

//C++⼀种实现封装的⽅式，⽤类将对象的属性与⽅法结合在⼀块，让对象更加完善，通过访问权限
//选择性的将其接⼝提供给外部的⽤⼾使⽤。

// public修饰的成员在类外可以直接被访问；protected和private修饰的成员在类外不能直接被访
//问，protected和private是⼀样的，以后继承章节才能体现出他们的区别。

// 访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌，如果后⾯没有
//访问限定符，作⽤域就到 }即类结束。

// class定义成员没有被访问限定符修饰时默认为private，struct默认为public。

// ⼀般成员变量都会被限制为private / protected，需要给别⼈使⽤的成员函数会放为public。


//定义在类里⾯的成员函数默认为inline。

//类定义了⼀个新的作⽤域，类的所有成员都在类的作⽤域中，在类体外定义成员时，需要使⽤::作
//⽤域操作符指明成员属于哪个类域。

// 类域影响的是编译的查找规则，下⾯程序中Init如果不指定类域Stack，那么编译器就把Init当成全
//局函数，那么编译时，找不到array等成员的声明 / 定义在哪⾥，就会报错。指定类域Stack，就是知
//道Init是成员函数，当前域找不到的array等成员，就会到类域中去查找。
//class Stack
//{
//public:
//	void STInit(int n = 4);
//
//private:
//	int* array;
//	int top;
//	int capacity;
//};
//
//// 声明和定义分离，需要指定类域
//void Stack::STInit(int n)
//{
//	array = (int*)malloc(sizeof(int) * n);
//	if (array == nullptr)
//	{
//		perror("malloc fail");
//		return;
//	}
//	top = 0;
//	capacity = n;
//}
//
//int main()
//{
//	Stack st;
//	st.STInit();
//
//	return 0;
//}

//⽤类类型在物理内存中创建对象的过程，称为类实例化出对象。

// 类是对象进⾏⼀种抽象描述，是⼀个模型⼀样的东西，限定了类有哪些成员变量，这些成员变量只
//是声明，没有分配空间，⽤类实例化出对象时，才会分配空间。

// ⼀个类可以实例化出多个对象，实例化出的对象 占⽤实际的物理空间，存储类成员变量。打个⽐
//⽅：类实例化出对象就像现实中使⽤建筑设计图建造出房⼦，类就像是设计图，设计图规划了有多
//少个房间，房间⼤⼩功能等，但是并没有实体的建筑存在，也不能住⼈，⽤设计图修建出房⼦，房
//⼦才能住⼈。同样类就像设计图⼀样，不能存储数据，实例化出的对象分配物理内存存储数据。

class Date
{
public:
	void DateInit(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void DatePrint()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}

private:
	// 这⾥只是声明，没有开空间
	int _year;
	int _month;
	int _day;

};

int main()
{
	// Date类实例化出对象d1和d2
	Date d1;
	Date d2;

	d1.DateInit(2004, 8, 27);
	d1.DatePrint();

	d2.DateInit(2004, 12, 17);
	d2.DatePrint();

	return 0;
}

